package com.yunpeng.aidevice.biz.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.yunpeng.aidevice.biz.service.IUserLoginBizService;
import com.yunpeng.aidevice.cache.service.ILoginUserCacheService;
import com.yunpeng.aidevice.common.constant.ConfigConstantValues;
import com.yunpeng.aidevice.common.dto.cache.LoginUserCacheDTO;
import com.yunpeng.aidevice.common.enums.MerchantStateEnum;
import com.yunpeng.aidevice.common.enums.ResultCodeEnum;
import com.yunpeng.aidevice.dao.constant.DictionariesConstant;
import com.yunpeng.aidevice.dao.model.entity.MerchantDO;
import com.yunpeng.aidevice.dao.model.entity.UserDO;
import com.yunpeng.aidevice.dao.service.IMerchantService;
import com.yunpeng.aidevice.dao.service.IRoleService;
import com.yunpeng.aidevice.dao.service.IUserService;
import com.yunpeng.common.dto.Result;
import com.yunpeng.common.exception.BizException;
import com.yunpeng.common.util.Md5Utils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;

/**
 * UserLoginBizServiceImpl
 *
 * @author : Moore(hemw)
 * @date : 2020-04-09
 */
@Service
public class UserLoginBizServiceImpl implements IUserLoginBizService {

    /**
     * 日志对象
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(UserLoginBizServiceImpl.class);

    @Resource
    private IMerchantService merchantService;

    @Resource
    private IUserService userService;

    @Resource
    private ILoginUserCacheService loginUserCacheService;

    @Resource
    private IRoleService roleService;

    @Override
    /**
     * 登录后台管理系统
     *
     * @param userCode 用户代码
     * @param password 密码
     * @return
     */
    public Result<JSONObject> loginBizSystem(String userCode, String password) {
        UserDO userDO = userService.getByCode(userCode);
        password = Md5Utils.getMd5(password);
        if (!userDO.getPassword().equalsIgnoreCase(password)) {
            LOGGER.error("1.login manage system failed password error .");
            return Result.fail(ResultCodeEnum.PASSWORD_ERROR);
        }
        //角色验证
        if (roleCheck(userDO.getCode())) {
            return doLogin(userDO);
        }
        return Result.fail(ResultCodeEnum.HAS_NOT_PERMISSION);
    }

    @Override
    /**
     * 登录商户系统
     *
     * @param userCode 用户代码
     * @param password 密码
     * @return
     */
    public Result<JSONObject> loginMerchantSystem(String userCode, String password) {
        UserDO userDO = userService.getByCode(userCode);
        if (StringUtils.isBlank(userDO.getMerchantCode())) {
            LOGGER.error("0.login merchant system failed password error .");
            return Result.fail(ResultCodeEnum.HAS_NOT_PERMISSION);
        }
        password = Md5Utils.getMd5(password);
        if (!userDO.getPassword().equalsIgnoreCase(password)) {
            LOGGER.error("1.login merchant system failed password error .");
            return Result.fail(ResultCodeEnum.PASSWORD_ERROR);
        }
        MerchantDO merchantDO = merchantService.getByCode(userDO.getMerchantCode(), userDO.getTenantCode());
        if (merchantDO == null || !userDO.getMerchantDefaultUser()) {
            LOGGER.error("2.login merchant system failed merchant user error .");
            return Result.fail(ResultCodeEnum.HAS_NOT_PERMISSION);
        }
        if (MerchantStateEnum.disabled.getValue().equalsIgnoreCase(merchantDO.getState())) {
            LOGGER.error("3.login merchant system failed merchant disabled error .");
            return Result.fail(ResultCodeEnum.DISABLED_MERCHANT);
        }
        if (LocalDateTime.now().isAfter(merchantDO.getInvalidDate())) {
            LOGGER.error("4.login merchant system failed merchant over invalid date error .");
            return Result.fail(ResultCodeEnum.MERCHANT_OVER_INVALID_DATE);
        }
        return doLogin(userDO);
    }


    @Override
    /**
     * 模拟商户登录
     *
     * @param merchantCode
     * @param loginUserCacheDTO
     * @return
     */
    public Result<JSONObject> mockMerchantLogin(String merchantCode, LoginUserCacheDTO loginUserCacheDTO) {
        UserDO userDO = userService.getByCode(loginUserCacheDTO.getCode(), loginUserCacheDTO.getMerchantCode(), loginUserCacheDTO.getTenantCode());
        if (userDO == null) {
            throw new BizException(ResultCodeEnum.USER_LOGIN_FAILED);
        }
        MerchantDO merchantDO = merchantService.getByCode(merchantCode, loginUserCacheDTO.getTenantCode());
        if (merchantDO == null) {
            throw new BizException(ResultCodeEnum.USER_LOGIN_FAILED);
        }
        //角色验证
        if (roleCheck(userDO.getCode())) {
            loginUserCacheDTO.setMerchantDefaultUser(true);
            loginUserCacheDTO.setMerchantCode(merchantCode);
            String accessToken = Md5Utils.getMd5(userDO.getCode().concat(Long.toString(System.currentTimeMillis())));
            loginUserCacheDTO.setAccessToken(accessToken);

            UserDO merchantUser = userService.getMerchantDefaultUser(merchantCode, loginUserCacheDTO.getTenantCode());
            if (merchantUser != null) {
                LOGGER.info("mock merchant login,{}", merchantUser);
                loginUserCacheDTO.setOrganizationPath(merchantUser.getOrganizationPath());
                loginUserCacheDTO.setOrganizationCode(merchantUser.getOrganizationCode());
                loginUserCacheDTO.setOrganizationName(merchantUser.getOrganizationName());
            }
            Result<Void> result = loginUserCacheService.put(loginUserCacheDTO);
            if (result.isSuccess()) {
                JSONObject resultData = new JSONObject();
                resultData.put(ConfigConstantValues.ACCESS_TOKEN, accessToken);
                return Result.success(resultData);
            }
            LOGGER.error("final.login failed,set user login cache failed {} .", loginUserCacheDTO);
            return Result.fail(ResultCodeEnum.USER_LOGIN_FAILED);
        }
        return Result.fail(ResultCodeEnum.HAS_NOT_PERMISSION);
    }

    @Override
    /**
     * 退出登录
     *
     * @param loginUserCacheDTO
     * @return
     */
    public Result<Void> unLogin(LoginUserCacheDTO loginUserCacheDTO) {
        return loginUserCacheService.remove(loginUserCacheDTO.getAccessToken());
    }

    //region 私有方法

    /**
     * 执行登录逻辑，写入登录缓存
     *
     * @param userDO
     * @return
     */
    private Result<JSONObject> doLogin(UserDO userDO) {
        String accessToken = Md5Utils.getMd5(userDO.getCode().concat(Long.toString(System.currentTimeMillis())));
        LoginUserCacheDTO loginUserCacheDTO = new LoginUserCacheDTO(accessToken, userDO.getId(), userDO.getCode(), userDO.getName(), userDO.getTenantCode(), userDO.getOrganizationCode(), userDO.getOrganizationPath(), userDO.getOrganizationName(), userDO.getPhone(), userDO.getNumber(), userDO.getSex(), userDO.getEmail(), userDO.getState(), userDO.getInvalidDate(), userDO.getFaceImgUrl(), userDO.getMerchantCode(), userDO.getMerchantDefaultUser());
        Result<Void> result = loginUserCacheService.put(loginUserCacheDTO);
        if (result.isSuccess()) {
            JSONObject resultData = new JSONObject();
            resultData.put(ConfigConstantValues.ACCESS_TOKEN, accessToken);
            return Result.success(resultData);
        }
        LOGGER.error("final.login failed,set user login cache failed {} .", loginUserCacheDTO);
        return Result.fail(ResultCodeEnum.USER_LOGIN_FAILED);
    }

    /**
     * 检查用户是否满足bms登录角色
     *
     * @param userCode
     * @return
     */
    private Boolean roleCheck(String userCode) {
        if (roleService.checkUserRole(DictionariesConstant.INSTANCE.getAdminRoleName(), userCode)) {
            return true;
        }
        return roleService.checkUserRole(DictionariesConstant.INSTANCE.getOperateAdminRoleName(), userCode);
    }

    //endregion
}
